home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
util
/
arc
/
PPCUnACE.lha
/
PPCUnACE
/
source.lha
/
Src
/
Unace.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-12-10
|
16KB
|
573 lines
/* ------------------------------------------------------------------------ */
/* */
/* Main file of public UNACE. */
/* */
/* ------------------------------------------------------------------------ */
//--------------- include general files ------------------------------------//
#include <ctype.h> // tolower()
#include <fcntl.h> // open()
#include <stdio.h> // printf() sprintf() remove()
#include <stdlib.h> // malloc()
#include <string.h> // str*()
#include <sys/stat.h> // S_I* AMIGA: fstat()
#if defined(AMIGA)
#include <error.h> // errno
#include <proto/dos.h>
#endif
#if defined(DOS) || defined(WIN32) || defined(WIN16)
#include <io.h> // lseek() open() read() write() eof() tell() close()
#if defined(WATCOM_C)
#include <dos.h> // lseek() open() read() write() eof() tell() close()
#endif
#endif
//--------------- include unace specific header files ----------------------//
#include "os.h"
#include "globals.h"
#include "portable.h"
#include "uac_comm.h"
#include "uac_crc.h"
#include "uac_crt.h"
#include "uac_dcpr.h"
#include "uac_sys.h"
#ifdef CRYPT
#include "unace_ps.h"
#endif /* CRYPT */
//--------------- BEGIN OF UNACE ROUTINES ----------------------------------//
void init_unace(void) // initializes unace
{
buf_rd =malloc(size_rdb * sizeof(ULONG)); // Allocate buffers: increase
buf =malloc(size_buf); // sizes when possible to speed
buf_wr =malloc(size_wrb); // up the program
readbuf=malloc(size_headrdb);
if (buf_rd ==NULL ||
buf ==NULL ||
buf_wr ==NULL ||
readbuf==NULL )
f_err = ERR_MEM;
make_crctable(); // initialize CRC table
dcpr_init(); // initialize decompression
set_handler(); // ctrl+break etc.
}
void done_unace(void)
{
if (buf_rd ) free(buf_rd );
if (buf ) free(buf );
if (buf_wr ) free(buf_wr );
if (readbuf ) free(readbuf );
if (dcpr_text) free(dcpr_text);
}
INT read_header(INT print_err) // reads any header from archive
{
USHORT rd,
head_size,
crc_ok;
LONG crc;
UCHAR *tp=readbuf;
lseek(archan, skipsize, SEEK_CUR); // skip ADDSIZE block
if (read(archan, &head, 4)<4)
return (0); // read CRC and header size
#ifdef HI_LO_BYTE_ORDER
WORDswap(&head.HEAD_CRC);
WORDswap(&head.HEAD_SIZE);
#endif
// read size_headrdb bytes into
head_size = head.HEAD_SIZE; // header structure
rd = (head_size > size_headrdb) ? size_headrdb : head_size;
if (read(archan, readbuf, rd) < rd)
return (0);
head_size -= rd;
crc = getcrc(CRC_MASK, readbuf, rd);
while (head_size) // skip rest of header
{
rd = (head_size > size_buf) ? size_buf : head_size;
if (read(archan, buf, rd) < rd)
return (0);
head_size -= rd;
crc = getcrc(crc, buf, rd);
}
head.HEAD_TYPE =*tp++; // generic buffer to head conversion
head.HEAD_FLAGS=BUFP2WORD(tp);
if (head.HEAD_FLAGS & ACE_ADDSIZE)
skipsize = head.ADDSIZE = BUF2LONG(tp); // get ADDSIZE
else
skipsize = 0;
// check header CRC
if (!(crc_ok = head.HEAD_CRC == (crc & 0xffff)) && print_err)
printf("\nError: archive is broken\n");
else
switch (head.HEAD_TYPE) // specific buffer to head conversion
{
case MAIN_BLK:
memcpy(mhead.ACESIGN, tp, acesign_len); tp+=acesign_len;
mhead.VER_MOD=*tp++;
mhead.VER_CR =*tp++;
mhead.HOST_CR=*tp++;
mhead.VOL_NUM=*tp++;
mhead.TIME_CR=BUFP2LONG(tp);
mhead.RES1 =BUFP2WORD(tp);
mhead.RES2 =BUFP2WORD(tp);
mhead.RES =BUFP2LONG(tp);
mhead.AV_SIZE=*tp++;
memcpy(mhead.AV, tp, rd-(USHORT)(tp-readbuf));
break;
case FILE_BLK:
fhead.PSIZE =BUFP2LONG(tp);
fhead.SIZE =BUFP2LONG(tp);
fhead.FTIME =BUFP2LONG(tp);
fhead.ATTR =BUFP2LONG(tp);
fhead.CRC32 =BUFP2LONG(tp);
fhead.TECH.TYPE =*tp++;
fhead.TECH.QUAL =*tp++;
fhead.TECH.PARM =BUFP2WORD(tp);
fhead.RESERVED =BUFP2WORD(tp);
fhead.FNAME_SIZE=BUFP2WORD(tp);
memcpy(fhead.FNAME, tp, rd-(USHORT)(tp-readbuf));
break;
// default: (REC_BLK and future things):
// do nothing 'cause isn't needed for extraction
}
return (crc_ok);
}
// maximum SFX module size
#define max_sfx_size 65536 // (needed by read_arc_head)
INT read_arc_head(void) // searches for the archive header and reads it
{
INT i,
flags,
buf_pos = 0;
LONG arc_head_pos,
old_fpos,
fpos = 0;
struct stat st;
fstat(archan, &st);
memset(buf, 0, size_buf);
while (tell(archan)<st.st_size && fpos < max_sfx_size)
{
old_fpos = fpos;
fpos += read(archan, &buf[buf_pos], size_buf - buf_pos);
for (i = 0; i < size_buf; i++) // look for the acesign
{
if (!memcmp(acesign, &buf[i], acesign_len))
{
// seek to the probable begin
// of the archive
arc_head_pos = old_fpos + i - buf_pos - bytes_before_acesign;
lseek(archan, arc_head_pos, SEEK_SET);
if (read_header(0)) // try to read archive header
{
flags = mhead.HEAD_FLAGS;
adat.sol = (flags & ACE_SOLID) > 0;
adat.vol = (flags & ACE_MULT_VOL) > 0;
adat.vol_num = mhead.VOL_NUM;
adat.time_cr = mhead.TIME_CR;
return (1);
}
}
}
// was no archive header,
// continue search
lseek(archan, fpos, SEEK_SET);
memcpy(buf, &buf[size_buf - 512], 512);
buf_pos = 512; // keep 512 old bytes
}
return (0);
}
INT open_archive(INT print_err) // opens archive (or volume)
{
CHAR av_str[80];
archan = open(aname, O_RDONLY | O_BINARY); // open file
if (archan == -1)
{
printf("\nError opening file %s", aname);
return (0);
}
if (!read_arc_head()) // read archive header
{
if (print_err)
printf("\nInvalid archive file: %s\n", aname);
close(archan);
return (0);
}
printf("\nProcessing archive: %s\n\n", aname);
if (head.HEAD_FLAGS & ACE_AV)
{
printf("Authenticity Verification:"); // print the AV
sprintf(av_str, "\ncreated on %d.%d.%d by ",
ts_day(adat.time_cr), ts_month(adat.time_cr), ts_year(adat.time_cr));
printf(av_str);
strncpy(av_str, mhead.AV, mhead.AV_SIZE);
av_str[mhead.AV_SIZE] = 0;
printf("%s\n\n", av_str);
}
comment_out("Main comment:"); // print main comment
return (1);
}
void get_next_volname(void) // get file name of next volume
{
CHAR *cp;
INT num;
if ((cp = (CHAR *) strrchr(aname, '.')) == NULL || !*(cp + 1))
num = -1;
else
{
cp++;
num = (*(cp + 1) - '0') * 10 + *(cp + 2) - '0';
if (!in(num, 0, 99))
num = -1;
if (in(*cp, '0', '9'))
num += (*cp - '0') * 100;
}
num++;
if (num < 100)
*cp = 'C';
else
*cp = num / 100 + '0';
*(cp + 1) = (num / 10) % 10 + '0';
*(cp + 2) = num % 10 + '0';
}
INT proc_vol(void) // opens volume
{
INT i;
CHAR s[80];
if (!fileexists(aname) || !f_allvol_pr)
{
do
{
sprintf(s,